package com.zjhn.ds.service.impl;

import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zjhn.ds.common.BizResult;
import com.zjhn.ds.common.Constant;
import com.zjhn.ds.common.exception.BizException;
import com.zjhn.ds.domain.dto.mt.AppStationMonitorDto;
import com.zjhn.ds.domain.dto.mt.AppStationMonitorV2Dto;
import com.zjhn.ds.domain.dto.mt.CurrentTaskDto;
import com.zjhn.ds.domain.dto.mt.QueueTaskDto;
import com.zjhn.ds.domain.dto.mt.SpotCurrentTaskDto;
import com.zjhn.ds.domain.dto.pc.SpotCheckDetailDto;
import com.zjhn.ds.domain.entity.erp.MesBookjob;
import com.zjhn.ds.domain.entity.erp.MesProBox;
import com.zjhn.ds.domain.entity.erp.Operator;
import com.zjhn.ds.domain.entity.erp.OutWorkBookJob;
import com.zjhn.ds.domain.entity.erp.PreList;
import com.zjhn.ds.domain.entity.erp.ProTask;
import com.zjhn.ds.domain.entity.erp.ProTaskDetail;
import com.zjhn.ds.domain.entity.erp.TradeOrderDetail;
import com.zjhn.ds.domain.entity.jlw.AssignTask;
import com.zjhn.ds.domain.entity.jlw.GroupSpinner;
import com.zjhn.ds.domain.entity.jlw.GroupStation;
import com.zjhn.ds.domain.entity.jlw.MachineChange;
import com.zjhn.ds.domain.entity.jlw.MaintenanceInfo;
import com.zjhn.ds.domain.entity.jlw.Proofing;
import com.zjhn.ds.domain.entity.jlw.ReportRecord;
import com.zjhn.ds.domain.entity.jlw.SpotCheck;
import com.zjhn.ds.domain.entity.jlw.Station;
import com.zjhn.ds.domain.entity.jlw.SwipeCardInfo;
import com.zjhn.ds.mapper.AssignTaskMapper;
import com.zjhn.ds.mapper.GroupSpinnerMapper;
import com.zjhn.ds.mapper.GroupStationMapper;
import com.zjhn.ds.mapper.MachineChangeMapper;
import com.zjhn.ds.mapper.MaintenanceInfoMapper;
import com.zjhn.ds.mapper.MesBookjobMapper;
import com.zjhn.ds.mapper.OperatorMapper;
import com.zjhn.ds.mapper.OutWorkBookJobMapper;
import com.zjhn.ds.mapper.PreListMapper;
import com.zjhn.ds.mapper.ProBoxMapper;
import com.zjhn.ds.mapper.ProTaskDetailMapper;
import com.zjhn.ds.mapper.ProTaskMapper;
import com.zjhn.ds.mapper.ProofingMapper;
import com.zjhn.ds.mapper.ReportRecordMapper;
import com.zjhn.ds.mapper.SpotCheckMapper;
import com.zjhn.ds.mapper.StationMapper;
import com.zjhn.ds.mapper.SwipeCardInfoMapper;
import com.zjhn.ds.mapper.TradeOrderDetailMapper;
import com.zjhn.ds.param.AppStationMonitorParam;
import com.zjhn.ds.param.FinishTaskParam;
import com.zjhn.ds.param.MachineChangeFinishParam;
import com.zjhn.ds.param.MaintenanceChangeParam;
import com.zjhn.ds.param.ProofingParam;
import com.zjhn.ds.param.ReportParam;
import com.zjhn.ds.param.SpotCheckParam;
import com.zjhn.ds.param.SwipeCardParam;
import com.zjhn.ds.service.AppStationMonitorService;
import com.zjhn.ds.utils.CommonUtil;
import com.zjhn.ds.utils.UserUtil;
import com.zjhn.ds.utils.base.CustomUtil;
import com.zjhn.ds.utils.base.DateUtil;
import com.zjhn.ds.utils.base.RedisCache;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @BelongsProject: ds_jlw
 * @BelongsPackage: com.zjhn.ds.service.impl
 * @Author: sxt
 * @CreateTime: 2023-10-09  09:44
 * @Description:
 * @Version: 1.0
 */
@Slf4j
@Service
public class AppStationMonitorServiceImpl implements AppStationMonitorService {

    @Resource
    private UserUtil userUtil;

    @Resource
    private CommonUtil commonUtil;

    @Resource
    private AssignTaskMapper assignTaskMapper;

    @Resource
    private SwipeCardInfoMapper swipeCardInfoMapper;

    @Resource
    private ProTaskDetailMapper proTaskDetailMapper;

    @Resource
    private GroupStationMapper groupStationMapper;

    @Resource
    private GroupSpinnerMapper groupSpinnerMapper;

    @Resource
    private StationMapper stationMapper;

    @Resource
    private ProTaskMapper proTaskMapper;

    @Resource
    private TradeOrderDetailMapper tradeOrderDetailMapper;

    @Resource
    private ProBoxMapper proBoxMapper;

    @Resource
    private ReportRecordMapper reportRecordMapper;

    @Resource
    private OperatorMapper operatorMapper;

    @Resource
    private MesBookjobMapper mesBookjobMapper;

    @Resource
    private OutWorkBookJobMapper outWorkBookJobMapper;

    @Resource
    private PreListMapper preListMapper;

    @Resource
    private SpotCheckMapper spotCheckMapper;

    @Resource
    private MaintenanceInfoMapper maintenanceInfoMapper;

    @Resource
    private MachineChangeMapper machineChangeMapper;

    @Resource
    private RedisCache redisCache;

    @Resource
    private ProofingMapper proofingMapper;

    /**
     * app机台监控页面数据
     *
     * @param param
     * @return
     */
    @Override
    public BizResult<AppStationMonitorV2Dto> stationMonitor(AppStationMonitorParam param) {
        AppStationMonitorV2Dto result = AppStationMonitorV2Dto.builder().build();

        List<AppStationMonitorDto> res = new ArrayList<>();
        // 挡车工负责工位信息
        List<GroupSpinner> groupSpinners = groupSpinnerMapper.selectList(new QueryWrapper<GroupSpinner>().eq("spinner_id", param.getSpinnerId()));
        if (groupSpinners.size() == 0)
            return BizResult.success(result);
        Set<String> groupIds = groupSpinners.stream().map(GroupSpinner::getGroupId).collect(Collectors.toSet());
        List<GroupStation> groupStations = groupStationMapper.selectList(new QueryWrapper<GroupStation>().in("group_id", groupIds));
        if (groupStations.size() == 0)
            return BizResult.success(result);
        Set<String> stationIds = groupStations.stream().map(GroupStation::getStationId).collect(Collectors.toSet());
        List<Station> stations = stationMapper.selectBatchIds(stationIds);

        // 获取agv状态
        Map<String, Integer> preListMap = new HashMap<>();
        List<PreList> preLists = preListMapper.selectList(new QueryWrapper<PreList>()
                .in("MasterId", stationIds).ne("CarryFlowStatus", 2));
        for (PreList preList : preLists)
            preListMap.put(preList.getMasterId(), preList.getCarryFlowStatus());

        Map<String, Integer> taskStatusMap = new HashMap<>();
        Map<String, AssignTask> assignTaskMap = new HashMap<>();
        // 获取机台当前刷卡信息
        List<SwipeCardInfo> swipeCardInfos = swipeCardInfoMapper.selectList(new QueryWrapper<SwipeCardInfo>().in("station_id", stationIds));
        Map<String, SwipeCardInfo> swipeCardInfoMap = new HashMap<>();
        if (swipeCardInfos.size() > 0) {
            swipeCardInfoMap = swipeCardInfos.stream().collect(Collectors.toMap(SwipeCardInfo::getStationId, c -> c));
            List<String> assignTaskIds = swipeCardInfos.stream().map(SwipeCardInfo::getAssignTaskId).collect(Collectors.toList());

            Set<String> proTaskDetailIds = new HashSet<>();
            Map<String, ProTaskDetail> proTaskDetailMap = new HashMap<>();
            if (assignTaskIds.size() > 0) {
                // 获取刷卡对应的派工任务
                List<AssignTask> assignTasks = assignTaskMapper.selectBatchIds(assignTaskIds);
                assignTaskMap = assignTasks.stream().collect(Collectors.toMap(AssignTask::getStationId, c -> c));

                // 进度
                proTaskDetailIds.addAll(assignTasks.stream().map(AssignTask::getTaskDetailId).collect(Collectors.toSet()));
                List<ProTaskDetail> proTaskDetails = proTaskDetailMapper.selectBatchIds(proTaskDetailIds);
                proTaskDetailMap.putAll(proTaskDetails.stream().collect(Collectors.toMap(ProTaskDetail::getId, c -> c)));
            }

            if (proTaskDetailIds.size() > 0) {
                List<AssignTask> all = assignTaskMapper.selectList(new QueryWrapper<AssignTask>().in("task_detail_id", proTaskDetailIds));
                Map<String, List<AssignTask>> assignTaskGroup = all.stream().collect(Collectors.groupingBy(AssignTask::getTaskDetailId));
                for (String taskDetailId : assignTaskGroup.keySet()) {
                    ProTaskDetail proTaskDetail = proTaskDetailMap.get(taskDetailId);
                    if (proTaskDetail == null)
                        return BizResult.fail("对应生产明细不存在");

                    List<AssignTask> collect = assignTaskGroup.get(taskDetailId);
                    BigDecimal taskFinishQty = BigDecimal.ZERO;
                    if (collect != null && collect.size() > 0)
                        taskFinishQty = collect.stream().map(AssignTask::getCompleteQty).reduce(BigDecimal.ZERO, BigDecimal::add);

                    int taskStatus = 1;
                    if (proTaskDetail.getWarnQty() != null) {
                        if (taskFinishQty.compareTo(BigDecimal.valueOf(proTaskDetail.getNumber())) >= 0)
                            taskStatus = 3;
                        else if (taskFinishQty.compareTo(proTaskDetail.getWarnQty()) >= 0)
                            taskStatus = 2;
                    } else {
                        if (taskFinishQty.compareTo(BigDecimal.valueOf(proTaskDetail.getNumber())) >= 0)
                            taskStatus = 3;
                    }

                    taskStatusMap.put(taskDetailId, taskStatus);
                }
            }

        }
        Integer stopQty = 0; // 关机
        Integer runQty = 0; // 正常
        Integer idleQty = 0; // 待机
        Integer faultQty = 0; // 故障
        for (Station station : stations) {
            // redis机台状态判断
            Integer status = commonUtil.getStationStatus(station.getId());
            if (status == 0) stopQty++;
            else if (status == 1) runQty++;
            else if (status == 2) idleQty++;
            else if (status == 3) faultQty++;

            AppStationMonitorDto build = AppStationMonitorDto.builder()
                    .stationId(station.getId())
                    .stationCode(station.getStationCode())
                    .stationName(station.getStationName())
                    .status(status)
//                    .styleCode()
//                    .completeQty()
//                    .assignQty()
                    .build();

            SwipeCardInfo swipeCardInfo = swipeCardInfoMap.get(station.getId());
            if (swipeCardInfo != null)
                build.setStyleCode(swipeCardInfo.getStyleCode());

            AssignTask assignTask = assignTaskMap.get(station.getId());
            if (assignTask != null) {
                build.setAssignQty(assignTask.getAssignQty());
                build.setCompleteQty(assignTask.getCompleteQty());
                build.setTaskStatus(taskStatusMap.get(assignTask.getTaskDetailId()));
            }

            Integer agvStatus = preListMap.get(station.getId());
            if (agvStatus != null && agvStatus > 1 && agvStatus < 5)
                build.setAgvStatus(agvStatus);

            res.add(build);
        }

        // 排序
        res = res.stream()
                .sorted(Comparator.comparing(c -> c.getStationCode().replace("-", "")))
                .collect(Collectors.toList());
        if (param.getOrder() == 2)
            res = res.stream().sorted(Comparator.comparing(AppStationMonitorDto::getStationCode).reversed()).collect(Collectors.toList());

        // 筛选
        if (param.getAgvStatus() != null)
            res = res.stream().filter(c -> c.getAgvStatus() == param.getAgvStatus()).collect(Collectors.toList());


        result.setStopQty(stopQty);
        result.setRunQty(runQty);
        result.setIdleQty(idleQty);
        result.setFaultQty(faultQty);
        result.setList(res);
        return BizResult.success(result);
    }

    /**
     * app获取工位当前刷卡任务
     *
     * @param stationId
     * @return
     */
    @Transactional
    @Override
    public BizResult<CurrentTaskDto> currentTask(String stationId) {
        CurrentTaskDto res = CurrentTaskDto.builder()
                .stationId(stationId)
                .build();

        SwipeCardInfo swipeCardInfo = swipeCardInfoMapper.selectOne(new QueryWrapper<SwipeCardInfo>().eq("station_id", stationId));
        if (swipeCardInfo == null)
            return BizResult.success(res);
        AssignTask assignTask = assignTaskMapper.selectById(swipeCardInfo.getAssignTaskId());
        if (assignTask == null) {
            // 派工任务删除
            swipeCardInfoMapper.deleteById(swipeCardInfo.getId());
            return BizResult.success(res);
        }

        // 获取对应明细
        ProTaskDetail proTaskDetail = proTaskDetailMapper.selectById(swipeCardInfo.getProTaskDetailId());
        if (proTaskDetail == null)
            return BizResult.fail("生产单明细不存在");

        // 对应生产单
        ProTask proTask = proTaskMapper.selectById(proTaskDetail.getTaskId());
        if (proTask == null)
            return BizResult.fail("生产单不存在");

        // 明细派工任务
        List<AssignTask> assignTasks = assignTaskMapper.selectList(
                new QueryWrapper<AssignTask>()
                        .eq("task_detail_id", swipeCardInfo.getProTaskDetailId())
        );

        // 获取改机信息
        MachineChange machineChange = machineChangeMapper.selectOne(new QueryWrapper<MachineChange>()
                .eq("station_id", stationId)
                .eq("finish", 0)
        );
        if (machineChange != null) {
            res.setMachineChange(true);
            res.setMachineChangeId(machineChange.getId());
        } else res.setMachineChange(false);

        // 获取维修信息
        MaintenanceInfo maintenanceInfo = maintenanceInfoMapper.selectOne(new QueryWrapper<MaintenanceInfo>()
                .eq("station_id", stationId)
                .eq("finish", 0)
        );
        if (maintenanceInfo != null) {
            res.setMaintenance(true);
            res.setMaintenanceId(maintenanceInfo.getId());
        } else res.setMaintenance(false);

        res.setSwipeCardId(swipeCardInfo.getId());
        res.setAssignTaskId(assignTask.getId());
        res.setProTaskDetailId(assignTask.getTaskDetailId());
        res.setProTaskCode(proTask.getCode());
        res.setStyleCode(swipeCardInfo.getStyleCode());
        res.setColorMain(swipeCardInfo.getColorMain());
        res.setSize(swipeCardInfo.getSize());
        res.setNeedle(swipeCardInfo.getNeedle());
        res.setStationCompleteQty(assignTask.getCompleteQty());
        res.setStationAssignQty(assignTask.getAssignQty());
        res.setDetailCompleteQty(assignTasks.stream().map(AssignTask::getCompleteQty).reduce(BigDecimal::add).orElse(BigDecimal.ZERO));
        res.setDetailQty(BigDecimal.valueOf(proTaskDetail.getNumber()));
        res.setProBoxCode(swipeCardInfo.getProBoxCode());
        res.setProBoxBookJobQty(swipeCardInfo.getProBoxBookJobQty());
        res.setPlanQty(swipeCardInfo.getPlanQty());
        res.setBatch(swipeCardInfo.getBatch());
        res.setPic(swipeCardInfo.getPic());
        return BizResult.success(res);
    }

    /**
     * app获取工位排队任务
     *
     * @param stationId
     * @return
     */
    @Override
    public BizResult<List<QueueTaskDto>> queueTask(String stationId) {
        List<QueueTaskDto> res = new ArrayList<>();
        List<AssignTask> assignTasks = assignTaskMapper.selectList(
                new QueryWrapper<AssignTask>()
                        .eq("station_id", stationId)
                        .eq("task_status", 1)
                        .orderByAsc("begin_time")
        );
        if (assignTasks.size() > 0) {
            // 生产单
            Set<String> taskIds = assignTasks.stream().map(AssignTask::getTaskId).collect(Collectors.toSet());
            List<ProTask> proTasks = proTaskMapper.selectBatchIds(taskIds);
            Map<String, ProTask> proTaskMap = proTasks.stream().collect(Collectors.toMap(ProTask::getId, c -> c));

            Set<String> taskDetailIds = assignTasks.stream().map(AssignTask::getTaskDetailId).collect(Collectors.toSet());
            // 生产明细
            List<ProTaskDetail> proTaskDetails = proTaskDetailMapper.selectBatchIds(taskDetailIds);
            Map<String, ProTaskDetail> proTaskDetailMap = proTaskDetails.stream().collect(Collectors.toMap(ProTaskDetail::getId, c -> c));

            // 交易单明细
            Set<String> orderDetailIds = proTaskDetails.stream().map(ProTaskDetail::getTradeOrderDetailId).collect(Collectors.toSet());
            List<TradeOrderDetail> tradeOrderDetails = tradeOrderDetailMapper.selectBatchIds(orderDetailIds);
            Map<String, TradeOrderDetail> orderDetailMap = tradeOrderDetails.stream().collect(Collectors.toMap(TradeOrderDetail::getId, c -> c));

            // 当前刷卡信息
            SwipeCardInfo swipeCardInfo = swipeCardInfoMapper.selectOne(new QueryWrapper<SwipeCardInfo>().eq("station_id", stationId));
            for (AssignTask assignTask : assignTasks) {
                ProTask proTask = proTaskMap.get(assignTask.getTaskId());
                if (proTask == null)
                    continue;
                ProTaskDetail proTaskDetail = proTaskDetailMap.get(assignTask.getTaskDetailId());
                if (proTaskDetail == null)
                    continue;
                TradeOrderDetail tradeOrderDetail = orderDetailMap.get(proTaskDetail.getTradeOrderDetailId());
                if (tradeOrderDetail == null)
                    continue;

                // 预计完成天数
                Date finishDate = DateUtil.dateAddMinute(assignTask.getBeginTime(), assignTask.getRequire());
                Integer intervalDays = 0;
                if (finishDate.compareTo(new Date()) > 0)
                    intervalDays = DateUtil.intervalDays(new Date(), finishDate);

                QueueTaskDto build = QueueTaskDto.builder()
                        .assignTaskId(assignTask.getId())
                        .proTaskDetailId(assignTask.getTaskDetailId())
                        .proTaskCode(proTask.getCode())
                        .assignQty(assignTask.getAssignQty())
                        .completeQty(assignTask.getCompleteQty())
                        .styleCode(tradeOrderDetail.getStyleCode())
                        .colorName(tradeOrderDetail.getColorName())
                        .needleCode(tradeOrderDetail.getNeedle())
                        .colorMain(tradeOrderDetail.getColorMain())
                        .size(tradeOrderDetail.getSize())
                        .finishDay(intervalDays)
                        .assignTime(DateUtil.formatDateToString(assignTask.getBeginTime()))
                        .current(0)
                        .build();
                if (swipeCardInfo != null && build.getAssignTaskId().equals(swipeCardInfo.getAssignTaskId())) {
                    build.setSwipeCardId(swipeCardInfo.getId());
                    build.setCurrent(1);
                }
                res.add(build);
            }

        }

        return BizResult.success(res);
    }

    /**
     * app确认报工
     *
     * @param param
     * @return
     */
    @Transactional
    @Override
    public BizResult<?> report(ReportParam param) {
        // 报工人信息
        Operator operator = operatorMapper.selectOne(
                new QueryWrapper<Operator>()
                        .eq("UserNo", param.getBookJobUser())
                        .eq("IsDeleted", 0)
        );
        if (operator == null)
            return BizResult.fail("报工人不存在");

        SwipeCardInfo swipeCardInfo = swipeCardInfoMapper.selectById(param.getSwipeCardId());
        if (swipeCardInfo == null)
            return BizResult.fail("刷卡信息不存在");

        AssignTask assignTask = assignTaskMapper.selectById(swipeCardInfo.getAssignTaskId());
        if (assignTask == null)
            return BizResult.fail("派工信息不存在");

        // 卡信息
        MesProBox mesProBox = proBoxMapper.selectOne(
                new QueryWrapper<MesProBox>()
                        .eq("Code", swipeCardInfo.getProBoxCode())
                        .eq("IsDeleted", 0)
        );
        if (mesProBox == null) {
            log.error("====[ERROR]====AppStationMonitorServiceImpl====report 卡信息不存在 proBoxCode:{}", swipeCardInfo.getProBoxCode());
            throw new BizException("卡信息不存在");
        }
        if (!mesProBox.getSendLastCard())
            if (mesProBox.getCurrentQty().add(param.getBookJobQty()).compareTo(mesProBox.getPlanQty()) > 0)
                return BizResult.fail("超出卡上报数量");

        String stepId = mesBookjobMapper.selectStep(mesProBox.getPDetailId());
        Integer mesBookJobStepCount = mesBookjobMapper.selectCount(
                new QueryWrapper<MesBookjob>()
                        .eq("PBoxId", mesProBox.getId())
                        .ne("StepId", stepId)
                        .eq("DataStatus", 1)
                        .eq("IsDeleted", 0)
        );
        if (mesBookJobStepCount > 0)
            return BizResult.fail("其他工序已在生产中");
        Integer outWorkBookJobStepCount = outWorkBookJobMapper.selectCount(
                new QueryWrapper<OutWorkBookJob>()
                        .eq("PBoxId", mesProBox.getId())
                        .ne("StepId", stepId)
        );
        if (outWorkBookJobStepCount > 0)
            return BizResult.fail("其他工序已在生产中");

        MesBookjob mesBookjob = new MesBookjob();
        mesBookjob.setId(CustomUtil.uuid2GUID(IdUtil.simpleUUID()));
        mesBookjob.setPBoxId(mesProBox.getId());
        mesBookjob.setPTaskId(mesProBox.getPTaskId());
        mesBookjob.setPDetailId(mesProBox.getPDetailId());

        mesBookjob.setOperatorId(operator.getId());
        mesBookjob.setOperatorName(operator.getRealName());

        mesBookjob.setBookJobQty(param.getBookJobQty());
        mesBookjob.setUngradedQty(BigDecimal.ZERO);
        mesBookjob.setLackedQty(BigDecimal.ZERO);
        mesBookjob.setStepId(stepId);
        mesBookjob.setDayTime(new Date());
        mesBookjob.setLastStep(0);
        mesBookjob.setIsRework(0);
        mesBookjob.setQcStepCheckOutUnPassQty(BigDecimal.ZERO);
        mesBookjob.setDataStatus(1);
        mesBookjob.setIsDeleted(0);
        mesBookjob.setCreateUserId(operator.getId());
        mesBookjob.setCreateTime(new Date());
        mesBookjob.setCreateUserName(operator.getRealName());
        mesBookjob.setMemo(commonUtil.getStationById(assignTask.getStationId()).getStationCode());
        mesBookjobMapper.insert(mesBookjob);

        // 更新pro_box 表信息
        mesProBox.setCurrentQty(mesProBox.getCurrentQty().add(param.getBookJobQty()));
        mesProBox.setCurrentStep(stepId);
        mesProBox.setBatchNo(param.getBatch());
        proBoxMapper.updateById(mesProBox);

        // 派工完成数记录
        assignTask.setCompleteQty(assignTask.getCompleteQty().add(param.getBookJobQty()));
        assignTaskMapper.updateById(assignTask);

        // 更新刷卡信息
        swipeCardInfo.setProBoxCode("--");
        swipeCardInfo.setPlanQty(BigDecimal.ZERO);
        swipeCardInfo.setProBoxBookJobQty(BigDecimal.ZERO);
        swipeCardInfo.setBatch(null);
        swipeCardInfoMapper.updateById(swipeCardInfo);

        // 报工记录
        ReportRecord reportRecord = ReportRecord.builder()
                .assignTaskId(assignTask.getId())
                .stationId(assignTask.getStationId())
                .proTaskDetailId(assignTask.getTaskDetailId())
                .bookJobId(mesBookjob.getId())
                .proBoxCode(mesProBox.getCode())
                .styleCode(swipeCardInfo.getStyleCode())
                .colorMain(swipeCardInfo.getColorMain())
                .size(swipeCardInfo.getSize())
                .needle(swipeCardInfo.getNeedle())
                .realName(operator.getRealName())
                .userNo(operator.getUserNo())
                .bookJobQty(param.getBookJobQty())
                .batch(param.getBatch())
                .build();
        reportRecordMapper.insert(reportRecord);

        return BizResult.success();
    }

    /**
     * app刷卡
     *
     * @param param
     * @return
     */
    @Transactional
    @Override
    public BizResult<?> swipeCard(SwipeCardParam param) {
        // 业务代码
        String cardNo = CustomUtil.getCardNo(param.getCode());
        MesProBox mesProBox = proBoxMapper.selectOne(new QueryWrapper<MesProBox>()
                .and(c -> c.eq("Code", cardNo).or().eq("Rfid", cardNo))
                .eq("IsDeleted", 0));
        if (mesProBox == null)
            return BizResult.fail("卡信息不存在");

        ProTaskDetail proTaskDetail = proTaskDetailMapper.selectById(mesProBox.getPDetailId());
        if (proTaskDetail == null)
            return BizResult.fail("生产明细不存在");
        TradeOrderDetail tradeOrderDetail = tradeOrderDetailMapper.selectById(proTaskDetail.getTradeOrderDetailId());
        if (tradeOrderDetail == null)
            return BizResult.fail("交易单明细不存在");

        // 派工任务
        AssignTask assignTask = assignTaskMapper.selectOne(
                new QueryWrapper<AssignTask>()
                        .eq("task_detail_id", proTaskDetail.getId())
                        .eq("station_id", param.getStationId()));
        if (assignTask == null)
            return BizResult.fail("卡对应的派工任务不存在");

        // 当前机台刷卡信息
        SwipeCardInfo swipeCardInfo = swipeCardInfoMapper.selectOne(
                new QueryWrapper<SwipeCardInfo>()
                        .eq("station_id", param.getStationId())
        );
        if (swipeCardInfo == null) {
            // 不存在刷卡信息
            swipeCardInfo = SwipeCardInfo.builder()
                    .assignTaskId(assignTask.getId())
                    .proTaskDetailId(proTaskDetail.getId())
                    .stationId(param.getStationId())
                    .styleCode(tradeOrderDetail.getStyleCode())
                    .colorMain(tradeOrderDetail.getColorMain())
                    .size(tradeOrderDetail.getSize())
                    .needle(tradeOrderDetail.getNeedle())
                    .pic(tradeOrderDetail.getImageUrl())
                    .proBoxCode(mesProBox.getCode())
                    .planQty(mesProBox.getPlanQty())
                    .proBoxBookJobQty(mesProBox.getCurrentQty())
                    .batch(mesProBox.getBatchNo())
                    .build();

            swipeCardInfoMapper.insert(swipeCardInfo);
        } else {
            // 存在刷卡信息
            swipeCardInfo.setAssignTaskId(assignTask.getId());
            swipeCardInfo.setProTaskDetailId(proTaskDetail.getId());
            swipeCardInfo.setStationId(param.getStationId());
            swipeCardInfo.setStyleCode(tradeOrderDetail.getStyleCode());
            swipeCardInfo.setColorMain(tradeOrderDetail.getColorMain());
            swipeCardInfo.setSize(tradeOrderDetail.getSize());
            swipeCardInfo.setNeedle(tradeOrderDetail.getNeedle());
            swipeCardInfo.setPic(tradeOrderDetail.getImageUrl());
            swipeCardInfo.setProBoxCode(mesProBox.getCode());
            swipeCardInfo.setPlanQty(mesProBox.getPlanQty());
            swipeCardInfo.setProBoxBookJobQty(mesProBox.getCurrentQty());
            swipeCardInfo.setBatch(mesProBox.getBatchNo());
            swipeCardInfoMapper.updateById(swipeCardInfo);
        }
        return BizResult.success();
    }

    /**
     * app 派工任务完成
     *
     * @param param
     * @return
     */
    @Transactional
    @Override
    public BizResult<?> finishTask(FinishTaskParam param) {
        if (StringUtils.isNotBlank(param.getSwipeCardId()))
            // 当前任务
            swipeCardInfoMapper.deleteById(param.getSwipeCardId());

        AssignTask assignTask = assignTaskMapper.selectById(param.getAssignTaskId());
        if (assignTask == null)
            return BizResult.fail("派工任务不存在");
        assignTask.setTaskStatus(2);
        assignTask.setCompleteTime(new Date());
        assignTaskMapper.updateById(assignTask);
        return BizResult.success();
    }

    /**
     * app抽查
     *
     * @param param
     * @return
     */
    @Override
    public BizResult<?> spotCheck(SpotCheckParam param) {
        List<Operator> operators = operatorMapper.selectList(new QueryWrapper<Operator>().eq("UserNo", param.getSpinner()));
        if (operators.size() == 0)
            return BizResult.fail("挡车工不存在");

        SpotCheck spotCheck = SpotCheck.builder()
                .date(DateUtil.formatDateToString(new Date(), DateUtil.DATE_FORMAT))
                .stationId(param.getStationId())
                .stationCode(param.getStationCode())
                .swipeCardId(param.getSwipeCardId())
                .assignTaskId(param.getAssignTaskId())
                .proTaskDetailId(param.getProTaskDetailId())
                .proTaskCode(param.getProTaskCode())
                .styleCode(param.getStyleCode())
                .colorMain(param.getColorMain())
                .size(param.getSize())
                .needle(param.getNeedle())
                .spotCheckQty(param.getSpotCheckQty())
                .rejectQty(param.getRejectQty())
                .passRate(param.getPassRate())
                .spinner(operators.get(0).getRealName())
                .khStyle(param.getKhStyle())
                .createUserName(userUtil.getUserInfo().getRealName())
                .memo(param.getMemo())
                .build();

        spotCheckMapper.insert(spotCheck);
        return BizResult.success();
    }

    /**
     * app抽检扫码获取工位当前刷卡任务
     * @param stationCode
     * @return
     */
    @Override
    public BizResult<SpotCurrentTaskDto> spotCheckCurrentTask(String stationCode) {
        SpotCurrentTaskDto res = SpotCurrentTaskDto.builder().build();

        Station station = stationMapper.selectOne(new QueryWrapper<Station>().eq("station_code", stationCode));
        if (station == null)
            return BizResult.fail("机台不存在");
        res.setStationId(station.getId());

        SwipeCardInfo swipeCardInfo = swipeCardInfoMapper.selectOne(
                new QueryWrapper<SwipeCardInfo>().eq("station_id", station.getId()));
        if (swipeCardInfo == null)
            return BizResult.success(res);
        AssignTask assignTask = assignTaskMapper.selectById(swipeCardInfo.getAssignTaskId());
        if (assignTask == null) {
            // 派工任务删除
            swipeCardInfoMapper.deleteById(swipeCardInfo.getId());
            return BizResult.success(res);
        }

        // 获取对应明细
        ProTaskDetail proTaskDetail = proTaskDetailMapper.selectById(swipeCardInfo.getProTaskDetailId());
        if (proTaskDetail == null)
            return BizResult.fail("生产单明细不存在");

        // 对应生产单
        ProTask proTask = proTaskMapper.selectById(proTaskDetail.getTaskId());
        if (proTask == null)
            return BizResult.fail("生产单不存在");

        // 明细派工任务
        List<AssignTask> assignTasks = assignTaskMapper.selectList(
                new QueryWrapper<AssignTask>()
                        .eq("task_detail_id", swipeCardInfo.getProTaskDetailId())
        );

        // 获取改机信息
        MachineChange machineChange = machineChangeMapper.selectOne(new QueryWrapper<MachineChange>()
                .eq("station_id", station.getId())
                .eq("finish", 0)
        );
        if (machineChange != null) {
            res.setMachineChange(true);
            res.setMachineChangeId(machineChange.getId());
        } else res.setMachineChange(false);

        // 获取维修信息
        MaintenanceInfo maintenanceInfo = maintenanceInfoMapper.selectOne(new QueryWrapper<MaintenanceInfo>()
                .eq("station_id", station.getId())
                .eq("finish", 0)
        );
        if (maintenanceInfo != null) {
            res.setMaintenance(true);
            res.setMaintenanceId(maintenanceInfo.getId());
        } else res.setMaintenance(false);

        // 获取打样信息
        Proofing proofing = proofingMapper.selectOne(new QueryWrapper<Proofing>()
                .eq("station_id", station.getId())
                .eq("finish", 0)
        );
        if (proofing != null) {
            res.setProofing(true);
            res.setProofingId(proofing.getId());
        } else res.setProofing(false);

        res.setStationId(station.getId());
        res.setSwipeCardId(swipeCardInfo.getId());
        res.setAssignTaskId(assignTask.getId());
        res.setProTaskDetailId(assignTask.getTaskDetailId());
        res.setProTaskCode(proTask.getCode());
        res.setStyleCode(swipeCardInfo.getStyleCode());
        res.setColorMain(swipeCardInfo.getColorMain());
        res.setSize(swipeCardInfo.getSize());
        res.setNeedle(swipeCardInfo.getNeedle());
        res.setStationCompleteQty(assignTask.getCompleteQty());
        res.setStationAssignQty(assignTask.getAssignQty());
        res.setDetailCompleteQty(assignTasks.stream().map(AssignTask::getCompleteQty).reduce(BigDecimal::add).orElse(BigDecimal.ZERO));
        res.setDetailQty(BigDecimal.valueOf(proTaskDetail.getNumber()));
        res.setProBoxCode(swipeCardInfo.getProBoxCode());
        res.setProBoxBookJobQty(swipeCardInfo.getProBoxBookJobQty());
        res.setPlanQty(swipeCardInfo.getPlanQty());
        res.setBatch(swipeCardInfo.getBatch());
        res.setPic(swipeCardInfo.getPic());
        res.setKhStyle(proTask.getKhStyle());
        return BizResult.success(res);
    }

    /**
     * app机台历史抽查记录
     * @param stationCode
     * @return
     */
    @Override
    public BizResult<List<SpotCheckDetailDto>> spotCheckHistory(String stationCode) {
        List<SpotCheckDetailDto> res = new ArrayList<>();
        List<SpotCheck> list = spotCheckMapper.selectList(
                new QueryWrapper<SpotCheck>()
                        .eq("station_code",stationCode)
                        .orderByAsc("create_time"));

        if (list.size() > 0)
            res.addAll(list.stream().map(c -> {
                SpotCheckDetailDto build = SpotCheckDetailDto.builder().build();
                BeanUtils.copyProperties(c, build);
                return build;
            }).collect(Collectors.toList()));

        return BizResult.success(res);
    }

    /**
     * app开始改机
     * @param param
     * @return
     */
    @Override
    public BizResult<?> machineChange(MaintenanceChangeParam param) {
        Integer i = operatorMapper.selectCount(new QueryWrapper<Operator>()
                .eq("UserNo", param.getUserNo()).eq("IsDeleted", 0));
        if (i == 0)
            return BizResult.fail("改机人员不存在");

        MachineChange machineChange = machineChangeMapper.selectOne(new QueryWrapper<MachineChange>()
                .eq("station_id", param.getStationId())
                .eq("finish", 0)
        );
        if (machineChange != null)
            return BizResult.fail("机台已存在改机信息");

        String equipmentId = commonUtil.getBindInfoById(param.getStationId());
        if (StringUtils.isBlank(equipmentId))
            return BizResult.fail("机台未绑定设备");
        String macAddress = commonUtil.getEquipmentById(equipmentId).getOutreachDevice();
        if (StringUtils.isBlank(macAddress))
            return BizResult.fail("机台未绑定设备");
        // 设置改机/维修标志位
        redisCache.setCacheObject(Constant.REDIS_PRE.MAINTENANCE_CHANGE_STATION + macAddress, 1);

        machineChange = MachineChange.builder()
                .stationId(param.getStationId())
                .stationCode(commonUtil.getStationById(param.getStationId()).getStationCode())
                .finish(0)
                .changeTime(DateUtil.formatDateToString(new Date()))
                .changeUserNo(param.getUserNo())
                .build();
        machineChangeMapper.insert(machineChange);

        return BizResult.success();
    }

    /**
     * app改机结束
     * @param param
     * @return
     */
    @Override
    public BizResult<?> machineChangeFinish(MachineChangeFinishParam param) {

        MachineChange machineChange = machineChangeMapper.selectById(param.getMachineChangeId());
        if (machineChange == null)
            return BizResult.fail("机台改机信息不存在");

        String equipmentId = commonUtil.getBindInfoById(machineChange.getStationId());
        if (StringUtils.isBlank(equipmentId))
            return BizResult.fail("机台未绑定设备");
        String macAddress = commonUtil.getEquipmentById(equipmentId).getOutreachDevice();
        if (StringUtils.isBlank(macAddress))
            return BizResult.fail("机台未绑定设备");
        // 设置改机/维修标志位
        redisCache.deleteObject(Constant.REDIS_PRE.MAINTENANCE_CHANGE_STATION + macAddress);

        machineChange.setFinish(1);
        machineChange.setSingleCost(param.getSingleCost());
        long seconds = Duration
                .between(DateUtil.formatStringToDate(machineChange.getChangeTime()).toInstant(), new Date().toInstant())
                .getSeconds();
        machineChange.setFinishTime(DateUtil.formatDateToString(new Date()));
        machineChange.setSpendTime(BigDecimal.valueOf(seconds));

        machineChangeMapper.updateById(machineChange);
        return BizResult.success();
    }

    /**
     * app开始维修
     * @param param
     * @return
     */
    @Override
    public BizResult<?> maintenance(MaintenanceChangeParam param) {
        Integer i = operatorMapper.selectCount(new QueryWrapper<Operator>()
                .eq("UserNo", param.getUserNo()).eq("IsDeleted", 0));
        if (i == 0)
            return BizResult.fail("维修人员不存在");

        MaintenanceInfo maintenanceInfo = maintenanceInfoMapper.selectOne(new QueryWrapper<MaintenanceInfo>()
                .eq("station_id", param.getStationId())
                .eq("finish", 0)
        );
        if (maintenanceInfo != null)
            return BizResult.fail("机台已存在维修信息");

        String equipmentId = commonUtil.getBindInfoById(param.getStationId());
        if (StringUtils.isBlank(equipmentId))
            return BizResult.fail("机台未绑定设备");
        String macAddress = commonUtil.getEquipmentById(equipmentId).getOutreachDevice();
        if (StringUtils.isBlank(macAddress))
            return BizResult.fail("机台未绑定设备");
        // 设置改机/维修标志位
        redisCache.setCacheObject(Constant.REDIS_PRE.MAINTENANCE_CHANGE_STATION + macAddress, 2);

        maintenanceInfo = MaintenanceInfo.builder()
                .stationId(param.getStationId())
                .stationCode(commonUtil.getStationById(param.getStationId()).getStationCode())
                .finish(0)
                .maintenanceTime(DateUtil.formatDateToString(new Date()))
                .maintenanceUserNo(param.getUserNo())
                .build();
        maintenanceInfoMapper.insert(maintenanceInfo);

        return BizResult.success();
    }

    /**
     * app维修结束
     * @param maintenanceId
     * @return
     */
    @Override
    public BizResult<?> maintenanceFinish(String maintenanceId) {
        MaintenanceInfo maintenanceInfo = maintenanceInfoMapper.selectById(maintenanceId);
        if (maintenanceInfo == null)
            return BizResult.fail("机台维修信息不存在");

        String equipmentId = commonUtil.getBindInfoById(maintenanceInfo.getStationId());
        if (StringUtils.isBlank(equipmentId))
            return BizResult.fail("机台未绑定设备");
        String macAddress = commonUtil.getEquipmentById(equipmentId).getOutreachDevice();
        if (StringUtils.isBlank(macAddress))
            return BizResult.fail("机台未绑定设备");
        // 设置改机/维修标志位
        redisCache.deleteObject(Constant.REDIS_PRE.MAINTENANCE_CHANGE_STATION + macAddress);

        maintenanceInfo.setFinish(1);
        long seconds = Duration
                .between(DateUtil.formatStringToDate(maintenanceInfo.getMaintenanceTime()).toInstant(), new Date().toInstant())
                .getSeconds();
        maintenanceInfo.setFinishTime(DateUtil.formatDateToString(new Date()));
        maintenanceInfo.setSpendTime(BigDecimal.valueOf(seconds));

        maintenanceInfoMapper.updateById(maintenanceInfo);
        return BizResult.success();
    }

    /**
     * app开始编织打样
     * @param param
     * @return
     */
    @Override
    public BizResult<?> proofing(ProofingParam param) {
        Integer i = operatorMapper.selectCount(new QueryWrapper<Operator>()
                .eq("UserNo", param.getUserNo()).eq("IsDeleted", 0));
        if (i == 0)
            return BizResult.fail("改机人员不存在");

        Proofing proofing = proofingMapper.selectOne(new QueryWrapper<Proofing>()
                .eq("station_id", param.getStationId())
                .eq("finish", 0)
        );
        if (proofing != null)
            return BizResult.fail("机台已存在打样信息");

        String equipmentId = commonUtil.getBindInfoById(param.getStationId());
        if (StringUtils.isBlank(equipmentId))
            return BizResult.fail("机台未绑定设备");
        String macAddress = commonUtil.getEquipmentById(equipmentId).getOutreachDevice();
        if (StringUtils.isBlank(macAddress))
            return BizResult.fail("机台未绑定设备");
        // 设置打样、维修、改机标志位
        redisCache.setCacheObject(Constant.REDIS_PRE.MAINTENANCE_CHANGE_STATION + macAddress, 1);

        proofing = Proofing.builder()
                .stationId(param.getStationId())
                .stationCode(commonUtil.getStationById(param.getStationId()).getStationCode())
                .finish(0)
                .proofingTime(DateUtil.formatDateToString(new Date()))
                .proofingUserNo(param.getUserNo())
                .build();
        proofingMapper.insert(proofing);

        return BizResult.success();
    }

    /**
     * app编织打样结束
     * @param proofingId
     * @return
     */
    @Override
    public BizResult<?> proofingFinish(String proofingId) {
        Proofing proofing = proofingMapper.selectById(proofingId);
        if (proofing == null)
            return BizResult.fail("机台打样信息不存在");

        String equipmentId = commonUtil.getBindInfoById(proofing.getStationId());
        if (StringUtils.isBlank(equipmentId))
            return BizResult.fail("机台未绑定设备");
        String macAddress = commonUtil.getEquipmentById(equipmentId).getOutreachDevice();
        if (StringUtils.isBlank(macAddress))
            return BizResult.fail("机台未绑定设备");
        // 设置改机/维修标志位
        redisCache.deleteObject(Constant.REDIS_PRE.MAINTENANCE_CHANGE_STATION + macAddress);

        proofing.setFinish(1);
        long seconds = Duration
                .between(DateUtil.formatStringToDate(proofing.getProofingTime()).toInstant(), new Date().toInstant())
                .getSeconds();
        proofing.setFinishTime(DateUtil.formatDateToString(new Date()));
        proofing.setSpendTime(BigDecimal.valueOf(seconds));

        proofingMapper.updateById(proofing);
        return BizResult.success();
    }
}
